﻿using GENERIC.MVVM.Model;
using System.Collections.ObjectModel;
using System.Linq.Expressions;
using System.Linq;
using System;
using GENERIC.MVVM.ViewModel.Interfaces;
using GENERIC.Service.Interfaces;

namespace GENERIC.ViewModel
{
    /// <summary>
    /// ListViewModel
    /// </summary>
    /// <typeparam name="TViewModel">Type du view model enfant</typeparam>
    /// <typeparam name="TEntityType">Type de l'entité</typeparam>
    /// <typeparam name="TServiceType">Type du service</typeparam>
    public abstract class ListViewModel<TViewModel, TEntityType, TServiceType> : ViewModelBase
        where TViewModel : ViewModel<TEntity>
        where TEntityType : ModelBase
        where TServiceType : IServiceBase
    {
        #region Attributs

        /// <summary>
        /// Obligation de recharger les données?
        /// </summary>
        protected bool _MustLoad = true;

        private ObservableCollection<TViewModelType> _items = null;
        private ObservableCollection<TViewModelType> _selectedItems = new ObservableCollection<TViewModelType>();

        #endregion

        #region Constructor

        /// <summary>
        /// Initialise une nouvelle instance
        /// </summary>
        public ListViewModel(TServiceType service, IViewModelFactory<TViewModel> vmFactory)
            : base()
        {
            Service = service;
            ViewModelFactory = vmFactory;
        }

        #endregion

        #region Proiperties

        /// <summary>
        /// Obtient ou définit le Service
        /// </summary>
        protected TServiceType Service
        {
            get;
            set;
        }

        private IViewModelFactory<TViewModel> ViewModelFactory { get; set; }

        /// <summary>
        /// La liste d’items du ViewModel
        /// </summary>
        public ObservableCollection<TViewModel> Items
        {
            get
            {
                //Si les items ne sont pas chargés, on laisse le soin
                //aux classes filles de fournir les données.
                if (_items == null || _MustLoad)
                {
                    IsBusy = true;
                    _items = LoadItems();
                    _MustLoad = false;
                    IsBusy = false;
                }
                return _items;
            }
            set
            {
                if (_items != value)
                {
                    _items = value;
                    RaisePropertyChanged<ObservableCollection<TViewModelType>>(() => Items);
                }
            }
        }

        /// <summary>
        /// Les différents éléments selectionnés
        /// </summary>
        public ObservableCollection<TViewModelType> SelectedItems
        {
            get { return _selectedItems; }
            set
            {
                if (_selectedItems != value)
                {
                    _selectedItems = value;
                    RaisePropertyChanged<ObservableCollection<TViewModelType>>(() => SelectedItems);
                }
            }
        }

        #endregion

        #region Methods

        protected abstract IQueryable<TEntityType> GetData();

        /// <summary>
        /// Méthode ABSTRAITE fournissant les différents items.
        /// </summary>
        /// <returns>Les items chargés</returns>
        protected virtual ObservableCollection<TViewModel> LoadItems()
        {
            var query = from m in GetData() select ViewModelFactory.ViewModel;
            return new ObservableCollection<TViewModel>(query);


            return list;
        }

        #endregion
    }

    /// <summary>
    /// Classe de base des list View Model
    /// </summary>
    /// <typeparam name="TViewModelType">Type du view model enfant</typeparam>
    /// <typeparam name="TEntityType">Type de l'entité</typeparam>
    /// /// <typeparam name="TServiceType">Service</typeparam>
    public abstract class DbListViewModel<TViewModelType, TEntityType, TServiceType> : ListViewModel<TViewModelType, TEntityType, TServiceType>
        where TViewModelType : ViewModel<TEntityType>
        where TEntityType : ModelBase
        where TServiceType : IService<TEntityType>
        
    {
        #region Constructor

        /// <summary>
        /// Initialise une nouvelle instance
        /// </summary>
        public DbListViewModel(TServiceType service)
            : base(service)
        {
        }

        #endregion

        #region Propriétés

        #endregion

        #region Methodes

        /// <summary>
        /// Obtenir les données
        /// </summary>
        /// <returns>Collection d'entités</returns>
        protected override IQueryable<TEntityType> GetData()
        {
            return Service.GetAll();
        }

        #endregion // Méthodes abstraites

        #region Méthodes

        /// <summary>
        /// Rafraichir les données
        /// </summary>
        public void Refresh()
        {
            _MustLoad = true;
            RaisePropertyChanged<ObservableCollection<TViewModelType>>(() => Items);
        }

        #endregion
    }
}
